home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 151-175 / scopedisk158 / dmouse / dmouse-handler.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  16KB  |  636 lines

  1.  
  2. #define DEBUG
  3. /*
  4.  *  DMOUSE-HANDLER.C
  5.  *
  6.  *  (c)Copyright 1989 by Matthew Dillon, All Rights Reserved
  7.  *
  8.  *  V1.20, last revision 3 August 1989
  9.  *
  10.  *  Note on upping the handler process priority.  This is done to cause the
  11.  *  handler task to get CPU before the current input event completes its
  12.  *  processing so intuition calls made by the process are executed before
  13.  *  the event is propogated.  If said intuition calls block, it's ok
  14.  *  because they are not blocking the input handler process.
  15.  */
  16.  
  17. #include "dmouse.h"
  18. #include <hardware/custom.h>
  19. #include <hardware/dmabits.h>
  20. #include <graphics/gfxmacros.h>
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. /*typedef struct Layer          LAYER;*/
  28. typedef IE  *IEP;
  29. typedef struct IORequest    IORequest;
  30.  
  31. __far extern struct Custom custom;
  32.  
  33. DMS    *Dms               = NULL;
  34. IBASE    *IntuitionBase           = NULL;
  35. GFXBASE *GfxBase           = NULL;
  36. struct LayersBase  *LayersBase = NULL;
  37. /*
  38. struct ExecBase    *SysBase    = NULL;
  39. */
  40. struct DosLibrary  *DOSBase    = NULL;
  41.  
  42. static PORT    *IOPort = NULL;     /*    For IPC messages          */
  43. static LIST    BlankList;        /*    list of external blanker programs */
  44.  
  45. static char    STimedout = 0;
  46. static char    MTimedout = 0;
  47. static long    STime = 0, MTime = 0;
  48. #ifdef DEBUG
  49. static long    DBFh = NULL;
  50. #endif
  51. static void    *ReqCache = NULL;   /*    to prevent massive AllocMem()s    */
  52.  
  53.  
  54. NS    Ns = {    0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET };
  55.  
  56.  
  57. IE DummyIE = { 0 };
  58.  
  59. short    NRMe    = 0;    /*  Don't Repeat Mouse Events   */
  60.  
  61. IE *handler();
  62.  
  63. int doipcmsg(short);
  64. void sendrequest(long, IE *);
  65. void DeleteBlanker(IORequest *);
  66. LAYER *WhichMouseLayer(void);
  67. LAYER *WhichMouseLayer(void);
  68.  
  69. void
  70. _main()
  71. {
  72.     DMS *dms;
  73.     IOR *ior;
  74.     INT addhand;
  75.     IBASE *ib;
  76.  
  77.     /*
  78.     SysBase = *(struct ExecBase **)4;
  79.     */
  80.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  81.     {
  82.     PROC *proc = (PROC *)FindTask(NULL);
  83.     proc->pr_ConsoleTask = NULL;
  84.     }
  85.     NRMe = 0;
  86.     dms = Dms = (DMS *)FindPort(PORTNAME);
  87.     if (!dms)
  88.     return;
  89.     dms->Port.mp_Flags = PA_SIGNAL;
  90.     dms->Port.mp_SigBit = AllocSignal(-1);
  91.     dms->Port.mp_SigTask = FindTask(NULL);
  92.     dms->HandTask = dms->Port.mp_SigTask;
  93.     ior = CreateStdIO(&dms->Port);
  94.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  95.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  96.     LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0);
  97.     IOPort = CreatePort("DMouse.ipc", 0);
  98.     NewList(&BlankList);
  99.  
  100.     if (!IntuitionBase || !GfxBase || !LayersBase)
  101.     goto startupfail;
  102.  
  103.     ib = IntuitionBase;
  104.  
  105.     clrmem(&addhand, sizeof(addhand));
  106.     addhand.is_Node.ln_Name = "DMouse";
  107.     addhand.is_Node.ln_Pri = dms->IPri;
  108.     addhand.is_Code = (FPTR)handler;
  109.     addhand.is_Data = NULL;
  110.  
  111.     if (OpenDevice("input.device", 0, ior, 0)) {
  112.     goto startupfail;
  113.     } else {
  114.     SCR *scr = NULL;
  115.     short sproff = 0;
  116.     long ipc_mask;
  117.  
  118.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  119.     ior->io_Command = IND_ADDHANDLER;
  120.     ior->io_Data = (APTR)&addhand;
  121.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  122.     DoIO(ior);
  123.  
  124.     ipc_mask = 1 << IOPort->mp_SigBit;
  125.  
  126.     for (;;) {
  127.         long sigs = Wait(SBF_C|(1<<dms->Port.mp_SigBit)|ipc_mask);
  128.         if (sigs & (1 << dms->Port.mp_SigBit)) {
  129.         REQ *msg;
  130.         while (msg = (REQ *)GetMsg(&dms->Port)) {
  131.             switch((long)msg->Msg.mn_Node.ln_Name) {
  132.             case REQ_SCREENON:
  133.             if (scr)
  134.                 CloseScreen(scr);
  135.             scr = NULL;
  136.             doipcmsg(0x82);
  137.             break;
  138.             case REQ_SCREENOFF:
  139.             if (scr)
  140.                 ScreenToFront(scr);
  141.             if (doipcmsg(0x83) == 0 && scr == NULL) {
  142.                 if (scr = OpenScreen(&Ns))
  143.                 SetRGB4(&scr->ViewPort, 0, 0, 0, 0);
  144.             }
  145.             break;
  146.             case REQ_MOUSEON:
  147.             if (sproff) {
  148.                 ON_SPRITE;
  149.                 sproff = 0;
  150.             }
  151.             doipcmsg(0x80);
  152.             break;
  153.             case REQ_MOUSEOFF:
  154.             /*
  155.              *  note, sometimes the sprite gets turned on again, so
  156.              *  we re-off it every mouse-ptr-timeout
  157.              */
  158.             if (doipcmsg(0x81) == 0) {
  159.                 WaitTOF();
  160.                 OFF_SPRITE;
  161.                 sproff = 1;
  162.             }
  163.             break;
  164.             case REQ_DOCMD:
  165.             {
  166.                 long fh = (long)Open("nil:", 1006);
  167.                 Execute(dms->Cmd, NULL, fh);
  168.                 if (fh)
  169.                 Close(fh);
  170.             }
  171.             break;
  172.             case REQ_RAWMOUSE:
  173.             {
  174.                 LAYER *layer;
  175.  
  176.                 NRMe = 0;
  177.                 Forbid();
  178.                 layer = WhichMouseLayer();
  179.                 if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) {
  180.                 WIN *win;
  181.                 if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) {
  182.                     if (dms->FBEnable || (win->Flags & WINDOWDEPTH)) {
  183.                     if (dms->Workbench)
  184.                         WindowToBack(win);
  185.                     else
  186.                         BehindLayer(0, layer);
  187.                     }
  188.                 } else if (ib->FirstScreen)
  189.                     ScreenToBack(ib->FirstScreen);
  190.                 }
  191.                 if (layer && layer->Window) {
  192.                 if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) {
  193.                     /*
  194.                      *    Note: Case where it is the 'first' click in a series, where dms->CTime is
  195.                      *          garbage, works properly no matter what DoubleClick returns.
  196.                      */
  197.                     if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) {
  198.                     if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, msg->ie_TimeStamp.tv_secs, msg->ie_TimeStamp.tv_micro))
  199.                         --dms->CLeft;
  200.                     else
  201.                         dms->CLeft = dms->Clicks - 1;
  202.                     dms->CTime = msg->ie_TimeStamp;
  203.                     dms->CWin = (WIN *)layer->Window;
  204.                     if (dms->CLeft == 0) {
  205.                         dms->CLeft = dms->Clicks;
  206.                         if (dms->FBEnable || (((WIN *)layer->Window)->Flags & WINDOWDEPTH)) {
  207.                         if (dms->Workbench)
  208.                             WindowToFront((WIN *)layer->Window);
  209.                         else
  210.                             UpfrontLayer(0, layer);
  211.                         }
  212.                     }
  213.                     }
  214.                 }
  215.                 if ((dms->AAEnable & 1) && (void *)layer->Window != (void *)ib->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) {
  216.                     if (!ib->ActiveWindow || !ib->ActiveWindow->FirstRequest)
  217.                     ActivateWindow((WIN *)layer->Window);
  218.                 }
  219.                 }
  220.                 Permit();
  221.             }
  222.             break;
  223.             case REQ_RAWKEY:
  224.             {
  225.                 LAYER *layer;
  226.  
  227.                 Forbid();
  228.                 layer = WhichMouseLayer();
  229.                 if (layer && layer->Window && (void *)layer->Window != (void *)ib->ActiveWindow) {
  230.                 if (!ib->ActiveWindow || !ib->ActiveWindow->FirstRequest)
  231.                     ActivateWindow((WIN *)layer->Window);
  232.                 }
  233.                 Permit();
  234.             }
  235.             break;
  236. #ifdef DEBUG
  237.             case REQ_DEBUG:
  238.             {
  239.                 char buf[128];
  240.                 if (!DBFh) {
  241.                 DBFh = Open("con:0/0/400/100/dmouse-debug", 1006);
  242.                 if (!DBFh)
  243.                     break;
  244.                 }
  245.                 sprintf(buf, "%02lx %04lx %04lx (%d,%d)\n",
  246.                 msg->ie_Class,
  247.                 msg->ie_Code,
  248.                 msg->ie_Qualifier,
  249.                 msg->rq_X,
  250.                 msg->rq_Y
  251.                 );
  252.                 Write(DBFh, buf, strlen(buf));
  253.             }
  254.             break;
  255.             case REQ_DEBUGOFF:
  256.             if (DBFh) {
  257.                 Close(DBFh);
  258.                 DBFh = NULL;
  259.             }
  260.             break;
  261. #endif
  262.             }
  263.             if (ReqCache == NULL && msg->Msg.mn_Length == sizeof(REQ))
  264.             ReqCache = (void *)msg;
  265.             else
  266.             FreeMem(msg, msg->Msg.mn_Length);
  267.         }
  268.         }
  269.         if (sigs & SBF_C)
  270.         break;
  271.  
  272.         /*
  273.          *    IPC request.
  274.          */
  275.  
  276.         if (sigs & ipc_mask) {
  277.         IORequest *ior;
  278.         while (ior = (IORequest *)GetMsg(IOPort)) {
  279.             long req = 0;
  280.  
  281.             if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  282.             FreeMem(ior, ior->io_Message.mn_Length);
  283.             continue;
  284.             }
  285.  
  286.             ior->io_Error = 0;
  287.             switch(ior->io_Command) {
  288.             case 0x80:    /* mouse on  */
  289.             req = REQ_MOUSEON;
  290.             break;
  291.             case 0x81:    /* mouse off */
  292.             req = REQ_MOUSEOFF;
  293.             MTimedout = 1;
  294.             break;
  295.             case 0x82:    /* screen on */
  296.             req = REQ_SCREENON;
  297.             break;
  298.             case 0x83:    /* screen off*/
  299.             req = REQ_SCREENOFF;
  300.             STimedout = 1;
  301.             break;
  302.             case 0x84:    /* add hand  */
  303.             AddHead(&BlankList, ior);
  304.             ior = NULL;
  305.             break;
  306.             case 0x85:    /* rem hand  */
  307.             DeleteBlanker(ior);
  308.             ior = NULL;
  309.             break;
  310.             }
  311.             if (req)
  312.             sendrequest(req, NULL);
  313.             if (ior)
  314.             ReplyMsg(&ior->io_Message);
  315.         }
  316.         }
  317.     }
  318. #ifdef DEBUG
  319.     if (DBFh) {
  320.         Close(DBFh);
  321.         DBFh = NULL;
  322.     }
  323. #endif
  324.     ior->io_Command = IND_REMHANDLER;
  325.     ior->io_Data = (APTR)&addhand;
  326.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  327.     DoIO(ior);
  328.  
  329.     ior->io_Command = IND_WRITEEVENT;    /*  NULL EVENT    */
  330.     ior->io_Length = sizeof(IE);
  331.     ior->io_Data = (APTR)&DummyIE;
  332.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  333.     DoIO(ior);
  334.     CloseDevice(ior);
  335.     {
  336.         MSG *msg;
  337.         while (msg = GetMsg(&dms->Port))
  338.         FreeMem(msg, msg->mn_Length);
  339.     }
  340.     if (scr)
  341.         CloseScreen(scr);
  342.  
  343.     if (sproff) {
  344.         ON_SPRITE;
  345.         sproff = 0;
  346.     }
  347.     }
  348.     goto closedown;
  349. startupfail:
  350.     dms->StartupError = 1;
  351.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  352.     Wait(SBF_C);
  353. closedown:
  354.     DeleteStdIO(ior);
  355. fail:
  356.     if (IOPort) {
  357.     IORequest *ior;     /*    wait for RemReq messages */
  358.  
  359.     doipcmsg(0x86);     /*  send closedown requests  */
  360.     Forbid();
  361.     while (GetHead(&BlankList)) {
  362.         WaitPort(IOPort);
  363.         while (ior = (IORequest *)GetMsg(IOPort)) {
  364.         if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  365.             FreeMem(ior, ior->io_Message.mn_Length);
  366.             continue;
  367.         }
  368.         if (ior->io_Command == 0x85)    /*  receive remove req  */
  369.             DeleteBlanker(ior);
  370.         else
  371.             ReplyMsg(&ior->io_Message);              /*  ignore other reqs   */
  372.         }
  373.     }
  374.     DeletePort(IOPort);
  375.     Permit();
  376.     }
  377.     if (IntuitionBase)
  378.     CloseLibrary((LIB *)IntuitionBase);
  379.     if (GfxBase)
  380.     CloseLibrary((LIB *)GfxBase);
  381.     if (LayersBase)
  382.     CloseLibrary((LIB *)LayersBase);
  383.     CloseLibrary((LIB *)DOSBase);
  384.     if (ReqCache)
  385.     FreeMem(ReqCache, sizeof(REQ));
  386.     Forbid();
  387.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  388. }
  389.  
  390. void
  391. DeleteBlanker(ior)
  392. IORequest *ior;
  393. {
  394.     IORequest *io2;
  395.  
  396.     ior->io_Error = 0;
  397.     for (io2 = (IORequest *)GetHead(&BlankList); io2; io2 = (IORequest *)GetSucc(io2)) {
  398.     if (io2->io_Unit == ior->io_Unit) {
  399.         Remove(io2);
  400.         if (ior)
  401.         ReplyMsg(&ior->io_Message);
  402.         ReplyMsg(&io2->io_Message);
  403.         ior = NULL;
  404.     }
  405.     }
  406.     if (ior) {
  407.     ior->io_Error = -1;
  408.     ReplyMsg(&ior->io_Message);
  409.     }
  410. }
  411.  
  412. doipcmsg(cmd)
  413. short cmd;
  414. {
  415.     short count = 0;
  416.     short flags = 1 << (cmd & 0x7F);    /*  enable flags */
  417.     IORequest *iob, *io;
  418.  
  419.     for (iob = (IORequest *)GetHead(&BlankList); iob; iob = (IORequest *)GetSucc(iob)) {
  420.     if (cmd == 0x86 || (iob->io_Flags & flags)) {
  421.         io = AllocMem(sizeof(IORequest), MEMF_PUBLIC|MEMF_CLEAR);
  422.         if (io) {
  423.         io->io_Command = cmd;
  424.         io->io_Unit = iob->io_Unit;
  425.         io->io_Message.mn_ReplyPort = IOPort;
  426.         io->io_Message.mn_Length = sizeof(IORequest);
  427.         PutMsg(iob->io_Message.mn_ReplyPort, &io->io_Message);
  428.         ++count;
  429.         }
  430.     }
  431.     }
  432.     return((int)count);
  433. }
  434.  
  435. /*
  436.  *  The INPUT.DEVICE HANDLER
  437.  */
  438.  
  439. __geta4 IE *
  440. CHandler(Ev)
  441. IE *Ev;
  442. {
  443.     IE *ev;
  444.     DMS *dms;
  445.  
  446.     dms = Dms;
  447.     for (ev = Ev; ev; ev = ev->ie_NextEvent) {  /*  chgd feb 1990 3/Ev->ev */
  448. #ifdef DEBUG
  449.     if (dms->Debug) {
  450.         if (ev->ie_Class != IECLASS_TIMER)
  451.         sendrequest(REQ_DEBUG, ev);
  452.     } else if (DBFh) {
  453.         sendrequest(REQ_DEBUGOFF, ev);
  454.     }
  455. #endif
  456.     switch(ev->ie_Class) {
  457.     case IECLASS_RAWMOUSE:
  458.         /*
  459.          *    Mouse events restore both the screen and mouse pointer.
  460.          */
  461.  
  462.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  463.         MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  464.         if (STimedout)
  465.         sendrequest(REQ_SCREENON, ev);
  466.         if (MTimedout)
  467.         sendrequest(REQ_MOUSEON, ev);
  468.         STimedout = MTimedout = 0;
  469.  
  470.         /*
  471.          *    Mouse Acceleration
  472.          */
  473.         {
  474.         short n;
  475.         short s;
  476.  
  477.         if (dms->Acc != 1) {
  478.             n = ev->ie_X;
  479.             s = 1;
  480.             if (n < 0) {
  481.             n = -n;
  482.             s = -1;
  483.             }
  484.             if (n > dms->AThresh)
  485.             ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  486.             n = ev->ie_Y;
  487.             s = 1;
  488.             if (n < 0) {
  489.             n = -n;
  490.             s = -1;
  491.             }
  492.             if (n > dms->AThresh)
  493.             ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  494.         }
  495.         }
  496.  
  497.         /*
  498.          *    Auto Activate and LMB (win/scrn front/bak)
  499.          */
  500.  
  501.         if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual))
  502.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  503.         if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) {
  504.         short old;
  505.         NRMe = 1;
  506.         if (ev->ie_Code != IECODE_NOBUTTON)
  507.             old = SetTaskPri(dms->Port.mp_SigTask, 21);
  508.         sendrequest(REQ_RAWMOUSE, ev);
  509.         if (ev->ie_Code != IECODE_NOBUTTON) {
  510.             SetTaskPri(dms->Port.mp_SigTask, old);
  511.             WaitTOF();  /*  cause a delay   */
  512.         }
  513.         }
  514.         break;
  515.     case IECLASS_RAWKEY:
  516.         /*
  517.          *    Keyboard events will kill the screen timeout but not
  518.          *    the mouse timeout.  Note that the priority of the
  519.          *    co-process must be upped to ensure it is able to make the
  520.          *    window active before the keystroke is passed further.
  521.          *
  522.          *    key releases are ignored
  523.          *
  524.          *    note: ie_Qualifier may or may not have bit 15 set
  525.          */
  526.         if (ev->ie_Code & 0x80)
  527.         break;
  528.         if (dms->AAEnable & 2) {
  529.         short old;
  530.         old = SetTaskPri(dms->Port.mp_SigTask, 21);
  531.         sendrequest(REQ_RAWKEY, ev);
  532.         SetTaskPri(dms->Port.mp_SigTask, old);
  533.         WaitTOF();  /*  cause a delay   */
  534.         }
  535.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  536.         if (STimedout) {
  537.         sendrequest(REQ_SCREENON, ev);
  538.         if (dms->MTo == 0)
  539.             sendrequest(REQ_MOUSEON, ev);
  540.         }
  541.         STimedout = 0;
  542.  
  543.         if (ev->ie_Code == dms->Code && (ev->ie_Qualifier | 0x8000) == dms->Qual) {
  544.         sendrequest(REQ_DOCMD, ev);
  545.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  546.         }
  547.         break;
  548.     case IECLASS_TIMER:
  549.         /*
  550.          *    On a timer event, if timeout has occured execute the operation
  551.          *    and reset the timeout.    Note that this will cause continuous
  552.          *    timeouts every STo and MTo seconds... required because at any
  553.          *    time Intuition might turn the mouse back on or open a screen or
  554.          *    something and I want the blanker's to work in the long run.
  555.          */
  556.         {
  557.         long old;
  558.         if (dms->Reset) {
  559.             dms->Reset = 0;
  560.             STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  561.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  562.         }
  563.         if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) {
  564.             STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10;
  565.             STimedout = 1;
  566.             MTimedout = 1;
  567.             if (old > -10) {
  568.             sendrequest(REQ_SCREENOFF, ev);
  569.             sendrequest(REQ_MOUSEOFF, ev);
  570.             }
  571.         }
  572.         if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) {
  573.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1;
  574.             MTimedout = 1;
  575.             if (old > -10)
  576.             sendrequest(REQ_MOUSEOFF, ev);
  577.         }
  578.         }
  579.         break;
  580.     }
  581.     }
  582.     return(Ev);
  583. }
  584.  
  585. void
  586. sendrequest(creq, ev)
  587. long creq;
  588. IE *ev;
  589. {
  590.     REQ *req;
  591.  
  592.     if (req = ReqCache)
  593.     ReqCache = NULL;
  594.     else
  595.     req = AllocMem(sizeof(REQ), MEMF_PUBLIC);
  596.  
  597.     if (req) {
  598.     req->Msg.mn_Node.ln_Name = (char *)creq;
  599.     req->Msg.mn_ReplyPort = NULL;
  600.     req->Msg.mn_Length = sizeof(REQ);
  601.     if (ev) {
  602.         req->ie_Class= ev->ie_Class;
  603.         req->ie_Code = ev->ie_Code;
  604.         req->ie_Qualifier = ev->ie_Qualifier;
  605.         req->ie_TimeStamp = ev->ie_TimeStamp;
  606.         req->rq_X = ev->ie_X;
  607.         req->rq_Y = ev->ie_Y;
  608.     }
  609.     PutMsg(&Dms->Port, (MSG *)req);
  610.     }
  611. }
  612.  
  613. LAYER *
  614. WhichMouseLayer()
  615. {
  616.     IBASE *ib = IntuitionBase;
  617.     LAYER *layer = NULL;
  618.     SCR *scr = ib->FirstScreen;
  619.  
  620.     for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) {
  621.     short mousey = ib->MouseY;
  622.     short mousex = ib->MouseX;
  623.     if (!(scr->ViewPort.Modes & LACE))
  624.         mousey >>= 1;
  625.     if (!(scr->ViewPort.Modes & HIRES))
  626.         mousex >>= 1;
  627.     if (layer = WhichLayer(&scr->LayerInfo, mousex, mousey - scr->ViewPort.DyOffset))
  628.         break;
  629.     if (mousey >= scr->ViewPort.DyOffset)
  630.         break;
  631.     }
  632.     return(layer);
  633. }
  634.  
  635.  
  636.